home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 February / EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso / earcd / comm2 / xbtx.lha / Source / GfxDisplay.cpp < prev    next >
C/C++ Source or Header  |  1995-12-03  |  31KB  |  1,421 lines

  1. /*
  2. **    $Id: GfxDisplay.cpp 1.7 1995/12/03 12:16:23 olsen Exp olsen $
  3. **
  4. **    :ts=4
  5. */
  6.  
  7. /*
  8.  * Amiga changes copyright © 1995 by Olaf Barthel, All Rights Reserved
  9.  *
  10.  * Copyright (c) 1992, 1993 Arno Augustin, Frank Hoering, University of
  11.  * Erlangen-Nuremberg, Germany.
  12.  * All rights reserved.
  13.  *
  14.  * Redistribution and use in source and binary forms, with or without
  15.  * modification, are permitted provided that the following conditions
  16.  * are met:
  17.  * 1. Redistributions of source code must retain the above copyright
  18.  *    notice, this list of conditions and the following disclaimer.
  19.  * 2. Redistributions in binary form must reproduce the above copyright
  20.  *    notice, this list of conditions and the following disclaimer in the
  21.  *    documentation and/or other materials provided with the distribution.
  22.  * 3. All advertising materials mentioning features or use of this software
  23.  *    must display the following acknowledgement:
  24.  *      This product includes software developed by the University of
  25.  *      Erlangen-Nuremberg, Germany.
  26.  * 4. Neither the name of the University nor the names of its contributors
  27.  *    may be used to endorse or promote products derived from this software
  28.  *    without specific prior written permission.
  29.  *
  30.  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
  31.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  32.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
  33.  * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  34.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  35.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  36.  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  37.  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  38.  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  39.  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  40.  *
  41.  * This software has not been validated by the ``Bundesamt fuer Zulassungen in
  42.  * der Telekommunikation'' of the ``Deutsche Bundepost Telekom'' and thus
  43.  * must not be used for accessing the BTX-Network of the Telekom in Germany.
  44.  *
  45.  * Diese Software hat keine Zulassung durch das Bundesamt fuer Zulassungen in
  46.  * der Telekommunikation der Deutschen Bundespost Telekom und darf daher nicht
  47.  * am Netz der Deutschen Bundespost Telekom in Deutschland betrieben werden.
  48.  */
  49.  
  50. /****************************************************************************/
  51.  
  52. #include <graphics/modeid.h>
  53. #include <hardware/blit.h>
  54. #include <exec/execbase.h>
  55.  
  56. #include <clib/intuition_protos.h>
  57. #include <clib/graphics_protos.h>
  58. #include <clib/utility_protos.h>
  59. #include <clib/keymap_protos.h>
  60. #include <clib/exec_protos.h>
  61. #include <clib/dos_protos.h>
  62.  
  63. #ifdef __SASC
  64. #include <pragmas/intuition_pragmas.h>
  65. #include <pragmas/graphics_pragmas.h>
  66. #include <pragmas/utility_pragmas.h>
  67. #include <pragmas/keymap_pragmas.h>
  68. #include <pragmas/exec_pragmas.h>
  69. #include <pragmas/dos_pragmas.h>
  70.  
  71. extern struct IntuitionBase *IntuitionBase;
  72. extern struct GfxBase        *GfxBase;
  73. extern struct ExecBase        *SysBase;
  74. extern struct DosLibrary    *DOSBase;
  75. extern struct Library        *KeymapBase;
  76. extern struct Library        *UtilityBase;
  77. #endif    // __SASC
  78.  
  79. #include <string.h>
  80. #include <stdio.h>
  81.  
  82. /******************************************************************************/
  83.  
  84. #ifndef _GFXDISPLAY_HPP
  85. #include "GfxDisplay.hpp"
  86. #endif
  87.  
  88. #ifndef _ATTRIBUTES_H
  89. #include "Attributes.h"
  90. #endif
  91.  
  92. #ifndef _RAWKEYS_H
  93. #include "RawKeys.h"
  94. #endif
  95.  
  96. /****************************************************************************/
  97.  
  98. #define SPREAD(v) ((((ULONG)v) << 24) | (((ULONG)v) << 16) | (((ULONG)v) << 8) | ((ULONG)v))
  99.  
  100. GfxDisplay::GfxDisplay()
  101. {
  102.     LONG i;
  103.  
  104.     BtxScreen = NULL;
  105.     BtxWindow = NULL;
  106.  
  107.     for(i = 0 ; i < 60 ; i++)
  108.         Pen[i] = -1;
  109.  
  110.     WaitingChar = -1;
  111.  
  112.     memset(&LocalBitMap,0,sizeof(LocalBitMap));
  113.     memset(btx_font,0,sizeof(btx_font));
  114.     memset(fullrow_bg,0,sizeof(fullrow_bg));
  115.     cur_fg = -1;
  116.     cur_bg = -1;
  117. }
  118.  
  119. GfxDisplay::~GfxDisplay()
  120. {
  121.     Close();
  122. }
  123.  
  124. VOID GfxDisplay::Close(VOID)
  125. {
  126.     free_DRCS();
  127.     free_font_pixmaps();
  128.  
  129.     FreeVec(LocalBitMap.Planes[0]);
  130.  
  131.     if(BtxWindow)
  132.     {
  133.         EraseRect(RPort,BtxWindow->BorderLeft,BtxWindow->BorderTop,BtxWindow->Width - (BtxWindow->BorderRight+1),BtxWindow->Height - (BtxWindow->BorderBottom+1));
  134.  
  135.         ReleaseColours();
  136.  
  137.         CloseWindow(BtxWindow);
  138.  
  139.         BtxWindow = NULL;
  140.     }
  141.  
  142.     ReleaseColours();
  143.  
  144.     if(BtxScreen)
  145.     {
  146.         CloseScreen(BtxScreen);
  147.  
  148.         BtxScreen = NULL;
  149.     }
  150. }
  151.  
  152. VOID GfxDisplay::MonitorData(int *btx_rows,int *btx_fontheight)
  153. {
  154.     rows        = btx_rows;
  155.     fontheight    = btx_fontheight;
  156. }
  157.  
  158. LONG GfxDisplay::Open(STRPTR PubScreenName,int XScale,int YScale,BOOL Direct)
  159. {
  160.     struct Screen *PubScreen;
  161.  
  162.     DirectRender = Direct;
  163.  
  164.     if(XScale < 1)
  165.         XScale = 1;
  166.  
  167.     if(YScale < 1)
  168.         YScale = 1;
  169.  
  170.     if(XScale > MAX_ZOOM)
  171.         XScale = MAX_ZOOM;
  172.  
  173.     if(XScale > MAX_ZOOM)
  174.         XScale = MAX_ZOOM;
  175.  
  176.     if(PubScreen = LockPubScreen((UBYTE *)PubScreenName))
  177.     {
  178.         VPort = &PubScreen -> ViewPort;
  179.  
  180.         if(InitColours())
  181.         {
  182.             for(;;)
  183.             {
  184.                 if(BtxWindow = OpenWindowTags(NULL,
  185.                     WA_PubScreen,        PubScreen,
  186.                     WA_InnerWidth,        40 * FONT_WIDTH        * XScale,
  187.                     WA_InnerHeight,        20 * FONT_HEIGHT    * YScale,
  188.                     WA_RMBTrap,         TRUE,
  189.                     WA_IDCMP,            IDCMP_MOUSEBUTTONS | IDCMP_RAWKEY | IDCMP_CLOSEWINDOW,
  190.                     WA_DepthGadget,        TRUE,
  191.                     WA_CloseGadget,        TRUE,
  192.                     WA_DragBar,            TRUE,
  193.                     WA_Title,            "XBTX Amiga",
  194.                     WA_AutoAdjust,        FALSE,
  195.                 TAG_DONE))
  196.                     break;
  197.                 else
  198.                 {
  199.                     if(YScale > 1)
  200.                     {
  201.                         YScale = (YScale + 1) / 2;
  202.                         continue;
  203.                     }
  204.  
  205.                     if(XScale > 1)
  206.                     {
  207.                         XScale = (XScale + 1) / 2;
  208.                         continue;
  209.                     }
  210.  
  211.                     ReleaseColours();
  212.                     break;
  213.                 }
  214.             }
  215.         }
  216.  
  217.         UnlockPubScreen(NULL,PubScreen);
  218.     }
  219.  
  220.     if(!BtxWindow)
  221.     {
  222.         UWORD Pens = (UWORD)~0;
  223.         ULONG DisplayID;
  224.  
  225.         DisplayID = FindBestModeID(
  226.             BIDTAG_NominalWidth,    40 * FONT_WIDTH        * XScale,
  227.             BIDTAG_NominalHeight,    20 * FONT_HEIGHT    * YScale,
  228.             BIDTAG_Depth,            8,
  229.         TAG_DONE);
  230.  
  231.         if(DisplayID == INVALID_ID)
  232.             return(-1);
  233.  
  234.         if(BtxScreen = OpenScreenTags(NULL,
  235.             SA_Depth,            8,
  236.             SA_DisplayID,        DisplayID,
  237.             SA_Overscan,        OSCAN_TEXT,
  238.             SA_SharePens,        TRUE,
  239.             SA_SysFont,         1,
  240.             SA_Interleaved,     TRUE,
  241.             SA_AutoScroll,        TRUE,
  242.             SA_Width,            40 * FONT_WIDTH        * XScale,
  243.             SA_Height,            20 * FONT_HEIGHT    * YScale,
  244.             SA_Pens,            &Pens,
  245.             SA_Quiet,            TRUE,
  246.             SA_ShowTitle,        FALSE,
  247.             SA_Behind,            TRUE,
  248.         TAG_DONE))
  249.         {
  250.             VPort = &BtxScreen->ViewPort;
  251.  
  252.             if(InitColours())
  253.             {
  254.                 if(!(BtxWindow = OpenWindowTags(NULL,
  255.                     WA_CustomScreen,    BtxScreen,
  256.                     WA_Width,            BtxScreen->Width,
  257.                     WA_Height,            BtxScreen->Height,
  258.                     WA_Backdrop,        TRUE,
  259.                     WA_Borderless,        TRUE,
  260.                     WA_RMBTrap,         TRUE,
  261.                     WA_IDCMP,            IDCMP_MOUSEBUTTONS | IDCMP_RAWKEY | IDCMP_CLOSEWINDOW,
  262.                 TAG_DONE)))
  263.                 {
  264.                     CloseWindow(BtxWindow);
  265.                     BtxWindow = NULL;
  266.  
  267.                     CloseScreen(BtxScreen);
  268.                     BtxScreen = NULL;
  269.                 }
  270.             }
  271.             else
  272.             {
  273.                 CloseScreen(BtxScreen);
  274.                 BtxScreen = NULL;
  275.             }
  276.         }
  277.     }
  278.  
  279.     if(BtxWindow)
  280.     {
  281.         RPort        = BtxWindow->RPort;
  282.         WindowPort    = BtxWindow->UserPort;
  283.         WindowMask    = 1UL << WindowPort->mp_SigBit;
  284.  
  285.         FgPen = 0;
  286.         BgPen = 0;
  287.  
  288.         SetABPenDrMd(RPort,Pen[FgPen],Pen[BgPen],JAM2);
  289.  
  290.         DisplayWidth    = (UWORD)(40 * FONT_WIDTH    * XScale);
  291.         DisplayHeight    = (UWORD)(20 * FONT_HEIGHT    * YScale);
  292.  
  293.         ScaleX            = XScale;
  294.         ScaleY            = YScale;
  295.  
  296.         InitBitMap(&LocalBitMap,8,2 * FONT_WIDTH * ScaleX,2 * FONT_HEIGHT * ScaleY);
  297.         InitRastPort(&LocalRPort);
  298.  
  299.         InitRastPort(&TempRPort);
  300.  
  301.         SetDrMd(&TempRPort,JAM1);
  302.  
  303.         if(LocalBitMap.Planes[0] = (PLANEPTR)AllocVec(LocalBitMap.Depth * LocalBitMap.BytesPerRow * LocalBitMap.Rows,MEMF_CHIP))
  304.         {
  305.             LONG PlaneSize = LocalBitMap.BytesPerRow * LocalBitMap.Rows;
  306.             LONG i;
  307.  
  308.             for(i = 1 ; i < LocalBitMap.Depth ; i++)
  309.                 LocalBitMap.Planes[i] = LocalBitMap.Planes[i - 1] + PlaneSize;
  310.  
  311.             LocalRPort.BitMap = &LocalBitMap;
  312.  
  313.             init_fonts();
  314.  
  315.             ScreenToFront(BtxWindow->WScreen);
  316.             ActivateWindow(BtxWindow);
  317.  
  318.             return(0);
  319.         }
  320.  
  321.         ReleaseColours();
  322.  
  323.         CloseWindow(BtxWindow);
  324.         BtxWindow = NULL;
  325.  
  326.         if(BtxScreen)
  327.         {
  328.             CloseScreen(BtxScreen);
  329.             BtxScreen = NULL;
  330.         }
  331.     }
  332.  
  333.     return(-1);
  334. }
  335.  
  336. VOID GfxDisplay::PutLine(STRPTR Line)
  337. {
  338.     if(Line)
  339.     {
  340.         int i,bg,len;
  341.  
  342.         bg = 32+4+PutIndex;
  343.  
  344.         SetFgPen(bg);
  345.         Fill(0,PutIndex*(*fontheight)*ScaleY,DisplayWidth, (*fontheight)*ScaleY);
  346.  
  347.         if((len = (int)strlen(Line)) > 40)
  348.             len = 40;
  349.  
  350.         for(i = 0 ; i < len ; i++)
  351.             xputc(Line[i],0,i,PutIndex,0,0,0,0,7,bg);
  352.  
  353.         PutIndex = (WORD)((PutIndex + 1) % (*rows));
  354.     }
  355.     else
  356.     {
  357.         PutIndex = 0;
  358.         xclearscreen();
  359.     }
  360. }
  361.  
  362. void GfxDisplay::init_fonts()
  363. {
  364.    static UBYTE raw_del[] = { 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
  365.                  0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
  366.                  0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f };
  367.  
  368.    extern UBYTE raw_font[];
  369.  
  370.    int n, i;
  371.  
  372.    /* primary graphic, 2nd suppl. mosaic, suppl. graphic, 3rd suppl. mosaic */
  373.    for(n=0; n<4*96; n++) {
  374.       btx_font[n].raw  = (UBYTE *)&raw_font[n*2*FONT_HEIGHT];
  375.       btx_font[n].bits = 1;
  376.       btx_font[n].link = NULL;
  377.       for(i=0; i<4; i++)  btx_font[n].map[i] = NULL;
  378.    }
  379.  
  380.    /* link chars into '1st supplementary mosaic' (L) set */
  381.    for(n=0; n<32; n++) {
  382.       btx_font[SUP1*96+n].link      = btx_font+SUP2*96+n;
  383.       btx_font[SUP1*96+n+32].link = btx_font+PRIM*96+n+32;
  384.       btx_font[SUP1*96+n+64].link = btx_font+SUP2*96+n+64;
  385.    }
  386.  
  387.    /* initialize the DEL character of the L set */
  388.    btx_font[L*96+0x7f-0x20].link = NULL;
  389.    btx_font[L*96+0x7f-0x20].raw = raw_del;
  390.    btx_font[L*96+0x7f-0x20].bits = 1;
  391.    for(i=0; i<4; i++)  btx_font[L*96+0x7f-0x20].map[i] = NULL;
  392.  
  393.    /* initialize DRCS font to all NULL's */
  394.    btx_font[DRCS*96+0].link = btx_font;    /* link 'SPACE' */
  395.    for(n=1; n<96; n++) {
  396.       btx_font[DRCS*96+n].bits = 0;
  397.       btx_font[DRCS*96+n].raw  = NULL;
  398.       btx_font[DRCS*96+n].link = NULL;
  399.       for(i=0; i<4; i++)  btx_font[DRCS*96+n].map[i] = NULL;
  400.    }
  401. }
  402.  
  403. void GfxDisplay::xputc(int c,int set,int x,int y,int xdouble,int ydouble,int underline,int diacrit,int fg,int bg)
  404. {
  405.    btxchar *ch, *dia;
  406.  
  407.    if(x<0 || y<0 || x>39 || y>(*rows)-1) return;
  408.  
  409.    ch = btx_font + set*96 + c - 0x20;
  410.  
  411.    /* folow the link pointer */
  412.    if(ch->link)  ch = ch->link;
  413.  
  414.    /* a yet undefined DRC should be drawn - draw a SPACE */
  415.    if(!ch->raw)  ch = btx_font;
  416.  
  417.    if(ch->bits==1) {
  418.       dia = diacrit ? &btx_font[SUPP*96 + diacrit - 0x20] : (btxchar *)NULL;
  419.       xdraw_normal_char(ch, x, y, xdouble, ydouble, underline, dia, fg, bg);
  420.    }
  421.    else {  /* 2/4 bits */
  422.       xdraw_multicolor_char(ch, x, y, xdouble, ydouble);
  423.    }
  424. }
  425.  
  426. void GfxDisplay::xdraw_normal_char(btxchar *ch,int x,int y,int xd,int yd,int ul,btxchar *dia,int fg,int bg)
  427. {
  428.    int size;
  429.  
  430.    if(fg==TRANSPARENT)    fg = 32+4+y;
  431.    if(bg==TRANSPARENT)    bg = 32+4+y;
  432.  
  433.    if(fg != cur_fg)
  434.    {
  435.        PreparePaintFg(fg);
  436.        PreparePaintFgBg(fg,bg);
  437.    }
  438.    else
  439.    {
  440.       if(bg != cur_bg)
  441.           PreparePaintFgBg(fg,bg);
  442.    }
  443.  
  444.    cur_fg = fg;
  445.    cur_bg = bg;
  446.  
  447.    size = yd*2 + xd;
  448.    /* Pixmap not available in this size, create it */
  449.    if(!ch->map[size])
  450.        ch->map[size] = rawfont2bitmap(ch->raw, (xd+1),(yd+1));
  451.  
  452.    if(dia && !dia->map[size])
  453.        dia->map[size] = rawfont2bitmap(dia->raw, (xd+1),(yd+1));
  454.  
  455.    if(ch->map[size])
  456.        DrawTemplate(ch->map[size],FgBgMinterms,x*FONT_WIDTH*ScaleX, y*(*fontheight)*ScaleY,FONT_WIDTH*ScaleX*(xd+1),(*fontheight)*ScaleY*(yd+1));
  457.  
  458.    if(dia && dia->map[size])
  459.        DrawTemplate(dia->map[size],FgMinterms,x*FONT_WIDTH*ScaleX, y*(*fontheight)*ScaleY,FONT_WIDTH*ScaleX*(xd+1),(*fontheight)*(yd+1)*ScaleY);
  460.  
  461.    if(ul)
  462.    {
  463.        SetFgPen(fg);
  464.        Fill(x*FONT_WIDTH*ScaleX,y*(*fontheight)*ScaleY+((*fontheight)-1)*(yd+1)*ScaleY,FONT_WIDTH*ScaleX*(xd+1),(yd+1)*ScaleY);
  465.    }
  466. }
  467.  
  468. void GfxDisplay::xdraw_multicolor_char(btxchar *ch,int x,int y,int xd,int yd)
  469. {
  470.     int size;
  471.  
  472.     size = yd*2 + xd;
  473.  
  474.     if(!ch->map[size])
  475.         ch->map[size] = createpixmapfromfont(ch->raw, (xd+1),(yd+1), ch->bits );
  476.  
  477.     if(ch->map[size])
  478.         DrawTemplate(ch->map[size],NULL,x*FONT_WIDTH*ScaleX, y*(*fontheight)*ScaleY,FONT_WIDTH*ScaleX*(xd+1),(*fontheight)*(yd+1)*ScaleY);
  479. }
  480.  
  481. void GfxDisplay::xclearscreen()
  482. {
  483.     int y, bg;
  484.  
  485.     for(y=0; y<(*rows); y++)
  486.     {
  487.         bg = 32+4+y;
  488.  
  489.         SetFgPen(bg);
  490.         Fill(0,y*(*fontheight)*ScaleY,DisplayWidth, (*fontheight)*ScaleY);
  491.     }
  492. }
  493.  
  494. void GfxDisplay::xcursor(int x,int y)
  495. {
  496.     Complement(x*FONT_WIDTH*ScaleX,y*(*fontheight)*ScaleY,FONT_WIDTH*ScaleX,(*fontheight)*ScaleY);
  497. }
  498.  
  499. struct BitMap * GfxDisplay::rawfont2bitmap(UBYTE *src, int xzoom, int yzoom)
  500. {
  501.     struct BitMap *Bits;
  502.  
  503.     if(Bits = NewBitMap(1,FONT_WIDTH*ScaleX * xzoom,FONT_HEIGHT * yzoom * ScaleY))
  504.     {
  505.         if(src)
  506.         {
  507.             struct RastPort *RPort = &TempRPort;
  508.             int              x,y;
  509.             UBYTE             pattern;
  510.  
  511.             RPort->BitMap = Bits;
  512.  
  513.             Bits->Depth = 1;
  514.             SetRast(RPort,0);
  515.             SetAPen(RPort,1);
  516.  
  517.             for(y = 0 ; y < FONT_HEIGHT * yzoom * ScaleY ; y++)
  518.             {
  519.                 pattern = src[2 * (y / (yzoom*ScaleY))];
  520.  
  521.                 for(x = 0 ; x < (FONT_WIDTH / 2) * (xzoom*ScaleX) ; x++)
  522.                 {
  523.                     if(pattern & (1 << (5 - (x / (xzoom*ScaleX)))))
  524.                         WritePixel(RPort,x,y);
  525.                 }
  526.  
  527.                 pattern = src[2 * (y / (yzoom*ScaleY)) + 1];
  528.  
  529.                 for(x = 0 ; x < (FONT_WIDTH / 2) * xzoom*ScaleX ; x++)
  530.                 {
  531.                     if(pattern & (1 << (5 - (x / (xzoom*ScaleX)))))
  532.                         WritePixel(RPort,x + (FONT_WIDTH / 2) * xzoom*ScaleX,y);
  533.                 }
  534.             }
  535.  
  536.             Bits->Depth = 8;
  537.         }
  538.     }
  539.  
  540.     return(Bits);
  541. }
  542.  
  543. struct BitMap * GfxDisplay::createpixmapfromfont(UBYTE *src,int xzoom,int yzoom,int bits)
  544. {
  545.     UBYTE *d = data;
  546.     int c,i,j,k,l,x,y,byteindex;
  547.     struct BitMap *Bits;
  548.  
  549.     if(Bits = NewBitMap(8,FONT_WIDTH*ScaleX * xzoom,FONT_HEIGHT * yzoom * ScaleY))
  550.     {
  551.         struct RastPort *RPort;
  552.         LONG LastPen = -1,ThisPen;
  553.  
  554.         RPort = &TempRPort;
  555.  
  556.         RPort->BitMap = Bits;
  557.  
  558.         SetRast(RPort,0);
  559.  
  560.         if(src)
  561.         {
  562.             for(y=0; y<FONT_HEIGHT; y++)
  563.             {
  564.                 byteindex = 0;
  565.  
  566.                 for(l=0; l<2; l++)
  567.                 {
  568.                     for(x=5; x>=0; x--)
  569.                     {
  570.                         for(c=0, k=0; k<bits; k++)
  571.                         {
  572.                             if(*(src+k*FONT_HEIGHT*2) & (1<<x) )
  573.                                 c |= 1<<k;
  574.                         }
  575.  
  576.                         for(j=0; j<xzoom*ScaleX; j++)
  577.                             row[byteindex++] = (UBYTE)(bits==4 ? c+16 : c+32);
  578.                     }
  579.  
  580.                     src++;
  581.                 }
  582.  
  583.                 for(j=0; j<(yzoom*ScaleY); j++)
  584.                 {
  585.                     for(i=0; i<byteindex; i++)
  586.                         *d++ = row[i];
  587.                 }
  588.             }
  589.  
  590.             d = data;
  591.  
  592.             for(y = 0 ; y < FONT_HEIGHT * yzoom * ScaleY ; y++)
  593.             {
  594.                 for(x = 0 ; x < FONT_WIDTH*ScaleX * xzoom ; x++)
  595.                 {
  596.                     ThisPen = Pen[*d++];
  597.  
  598.                     if(LastPen != ThisPen)
  599.                         SetAPen(RPort,LastPen = ThisPen);
  600.  
  601.                     WritePixel(RPort,x,y);
  602.                 }
  603.             }
  604.         }
  605.     }
  606.  
  607.     return(Bits);
  608. }
  609.  
  610. void GfxDisplay::define_raw_DRC(int c,UBYTE *data, int bits)
  611. {
  612.     struct btxchar *ch = btx_font + DRCS*96 + c - 0x20;
  613.     int n;
  614.  
  615.     if(ch->raw)
  616.         delete ch->raw;
  617.  
  618.     for(n=0; n<4; n++)
  619.     {
  620.         if(ch->map[n])
  621.         {
  622.             DisposeBitMap(ch->map[n]);
  623.             ch->map[n] = NULL;
  624.         }
  625.     }
  626.  
  627.     if(ch->raw = new UBYTE[2*FONT_HEIGHT*bits])
  628.     {
  629.         memset(ch->raw,0,2*FONT_HEIGHT*bits);
  630.  
  631.         ch->bits = (UBYTE)bits;
  632.  
  633.         for(n=0; n<2*FONT_HEIGHT*bits; n++)
  634.             ch->raw[n] = data[n];
  635.  
  636.         ch->link = NULL;
  637.     }
  638. }
  639.  
  640. void GfxDisplay::free_DRCS()
  641. {
  642.     int i, n;
  643.  
  644.     btx_font[DRCS*96+0].link = btx_font;    /* link 'SPACE' */
  645.  
  646.     for(n=DRCS*96+1; n<(DRCS+1)*96; n++)
  647.     {
  648.         if(btx_font[n].raw)
  649.         {
  650.             delete btx_font[n].raw;
  651.             btx_font[n].raw = NULL;
  652.         }
  653.         for(i=0; i<4; i++)
  654.         {
  655.             if(btx_font[n].map[i])
  656.             {
  657.                 DisposeBitMap(btx_font[n].map[i]);
  658.                 btx_font[n].map[i] = NULL;
  659.             }
  660.             btx_font[n].link = NULL;
  661.             btx_font[n].bits = 0;
  662.         }
  663.     }
  664. }
  665.  
  666. void GfxDisplay::free_font_pixmaps()
  667. {
  668.     int i, n;
  669.  
  670.     for(n=0; n<6*96; n++)
  671.     {
  672.         if(!btx_font[n].link)
  673.         {
  674.             for(i=0; i<4; i++)
  675.             {
  676.                 if(btx_font[n].map[i])
  677.                 {
  678.                     DisposeBitMap(btx_font[n].map[i]);
  679.                     btx_font[n].map[i] = NULL;
  680.                 }
  681.             }
  682.         }
  683.     }
  684. }
  685.  
  686. void GfxDisplay::default_colors()
  687. {
  688.     init_colormap();
  689.     store_colors();
  690. }
  691.  
  692. void GfxDisplay::store_colors()
  693. {
  694.     int n;
  695.  
  696. //    for(n = 0 ; n < 16 ; n++)
  697. //        SetColour(n,colormap[n].red,colormap[n].green,colormap[n].blue);
  698.  
  699.     for(n = 0 ; n < 8 ; n++)
  700.     {
  701.         SetColour(n + 16,colormap[n + 16].red,colormap[n + 16].green,colormap[n + 16].blue);    // clut 2
  702.         SetColour(n + 24,colormap[n + 24].red,colormap[n + 24].green,colormap[n + 24].blue);    // clut 3
  703.     }
  704.  
  705.     for(n = 0 ; n < 4 ; n++)    // dclut
  706.         SetColour(32 + n,colormap[32 + n].red,colormap[32 + n].green,colormap[32 + n].blue);
  707.  
  708.     for(n = 0 ; n < 24 ; n++)
  709.         SetColour(32 + 4 + n,colormap[32 + 4 + n].red,colormap[32 + 4 + n].green,colormap[32 + 4 + n].blue);
  710. }
  711.  
  712. void GfxDisplay::init_colormap()
  713. {
  714.    int n;
  715.  
  716.    /* clut 0 + clut 1 */
  717.    for(n=0; n<16; n++) {  /* page 112) */
  718.       if(n==8)    { colormap[n] = colormap[0]; continue; }
  719.       colormap[n].red    = (UBYTE)(((n&1)>0) ? ( ((n&8)==0) ? 0xff : 0x7f ) : 0);
  720.       colormap[n].green = (UBYTE)(((n&2)>0) ? ( ((n&8)==0) ? 0xff : 0x7f ) : 0);
  721.       colormap[n].blue    = (UBYTE)(((n&4)>0) ? ( ((n&8)==0) ? 0xff : 0x7f ) : 0);
  722.    }
  723.  
  724.    /* clut 2 + clut 3 */
  725.    for(n=0; n<8; n++) {
  726.       colormap[n+16].red   = colormap[n+24].red   = (UBYTE)(n&1 ? 0xff : 0);
  727.       colormap[n+16].green = colormap[n+24].green = (UBYTE)(n&2 ? 0xff : 0);
  728.       colormap[n+16].blue  = colormap[n+24].blue  = (UBYTE)(n&4 ? 0xff : 0);
  729.    }
  730.  
  731.    /* DCLUT */
  732.    for(n=0; n<4; n++) {
  733.       colormap[32+n].red   = colormap[n].red;
  734.       colormap[32+n].green = colormap[n].green;
  735.       colormap[32+n].blue  = colormap[n].blue;
  736.       dclut[n] = n;
  737.    }
  738.  
  739.    /* fullrow background (BLACK) */
  740.    for(n=0; n<24; n++) {
  741.       colormap[32+4+n].red     = colormap[0].red;
  742.       colormap[32+4+n].green = colormap[0].green;
  743.       colormap[32+4+n].blue  = colormap[0].blue;
  744.       fullrow_bg[n] = 0;
  745.    }
  746. }
  747.  
  748. void GfxDisplay::define_color(int index,int r,int g,int b)    // 4 bit pro Eintrag
  749. {
  750.     int i;
  751.  
  752.     r &= 15;
  753.     g &= 15;
  754.     b &= 15;
  755.  
  756.     r = (r << 4) | r;
  757.     g = (g << 4) | g;
  758.     b = (b << 4) | b;
  759.  
  760.     colormap[index].red   = (UBYTE)r;
  761.     colormap[index].green = (UBYTE)g;
  762.     colormap[index].blue  = (UBYTE)b;
  763.     SetColour(index,r,g,b);
  764.  
  765.     /* if DCLUT contains this color, change DCLUT color too */
  766.     for(i=0; i<4; i++)
  767.     {
  768.         if(dclut[i]==index)
  769.             define_DCLUT(i, index);
  770.     }
  771.  
  772.     /* if fullrow_bg contains this color, change fullrow color too */
  773.     for(i=0; i<24; i++)
  774.     {
  775.         if(fullrow_bg[i]==index)
  776.             define_fullrow_bg(i, index);
  777.     }
  778. }
  779.  
  780. void GfxDisplay::define_DCLUT(int entry,int index)
  781. {
  782.    dclut[entry] = index;
  783.    colormap[32+entry].red    = colormap[index].red;
  784.    colormap[32+entry].green = colormap[index].green;
  785.    colormap[32+entry].blue    = colormap[index].blue;
  786.  
  787.    SetColour(32 + entry,colormap[32 + entry].red,colormap[32 + entry].green,colormap[32 + entry].blue);
  788. }
  789.  
  790. void GfxDisplay::define_fullrow_bg(int row,int index)
  791. {
  792.    fullrow_bg[row] = index;
  793.    colormap[32+4+row].red    = colormap[index].red;
  794.    colormap[32+4+row].green = colormap[index].green;
  795.    colormap[32+4+row].blue    = colormap[index].blue;
  796.  
  797.    SetColour(32 + 4 + row,colormap[32 + 4 + row].red,colormap[32 + 4 + row].green,colormap[32 + 4 + row].blue);
  798. }
  799.  
  800. /******************************************************************************/
  801.  
  802. #define V0H0    (0)
  803. #define V0H1    (NANBC | ANBNC | NANBC | ANBC)
  804. #define V1H0    (NABNC | ABNC | NABC | ABC)
  805. #define V1H1    (NANBC | NANBNC | NABC | NABNC | ANBC | ANBNC | ABC | ABNC)
  806.  
  807. #define PAINT_a (NANBC | ANBC | NABNC | ABNC | NABC | ABC)
  808. #define PAINT_b (ANBC | NANBC)
  809.  
  810. VOID GfxDisplay::PreparePaintFgBg(UBYTE Fore,UBYTE Back,UBYTE *Minterms)
  811. {
  812.     UBYTE Mask,Term,i;
  813.  
  814.     if(!Minterms)
  815.         Minterms = FgBgMinterms;
  816.  
  817.     Fore = (UBYTE)Pen[Fore];
  818.     Back = (UBYTE)Pen[Back];
  819.  
  820.     for(i = 0 ; i < 8 ; i++)
  821.     {
  822.         Mask = (UBYTE)(1 << i);
  823.  
  824.         if(Fore & Mask)
  825.         {
  826.             if(Back & Mask)
  827.                 Term = V1H1;
  828.             else
  829.                 Term = V1H0;
  830.         }
  831.         else
  832.         {
  833.             if(Back & Mask)
  834.                 Term = V0H1;
  835.             else
  836.                 Term = V0H0;
  837.         }
  838.  
  839.         Minterms[i] = Term;
  840.     }
  841. }
  842.  
  843. VOID GfxDisplay::PreparePaintFg(UBYTE Fore,UBYTE *Minterms)
  844. {
  845.     UBYTE Mask,Term,i;
  846.  
  847.     if(!Minterms)
  848.         Minterms = FgMinterms;
  849.  
  850.     Fore = (UBYTE)Pen[Fore];
  851.  
  852.     for(i = 0 ; i < 8 ; i++)
  853.     {
  854.         Mask = (UBYTE)(1 << i);
  855.  
  856.         if(Fore & Mask)
  857.             Term = PAINT_a;
  858.         else
  859.             Term = PAINT_b;
  860.  
  861.         Minterms[i] = Term;
  862.     }
  863. }
  864.  
  865. VOID GfxDisplay::DrawTemplate(CONST struct BitMap *BitMap,CONST UBYTE *Minterms,UWORD Left,UWORD Top,UWORD Width,UWORD Height)
  866. {
  867.     Left    += BtxWindow->BorderLeft;
  868.     Top        += BtxWindow->BorderTop;
  869.  
  870.     if(Minterms)
  871.     {
  872.         if(DirectRender)
  873.         {
  874.             LONG i;
  875.  
  876.             for(i = 0 ; i < 8 ; i++)
  877.             {
  878.                 SetWriteMask(RPort,1 << i);
  879.                 BltBitMapRastPort((struct BitMap *)BitMap,0,0,RPort,Left,Top,Width,Height,Minterms[i]);
  880.             }
  881.  
  882.             SetWriteMask(RPort,~0);
  883.         }
  884.         else
  885.         {
  886.             LONG i;
  887.  
  888.             SetRast(&LocalRPort,0);
  889.  
  890.             ClipBlit(RPort,Left,Top,&LocalRPort,0,0,Width,Height,0xC0);
  891.  
  892.             for(i = 0 ; i < 8 ; i++)
  893.                 BltBitMap((struct BitMap *)BitMap,0,0,&LocalBitMap,0,0,Width,Height,Minterms[i],1 << i,NULL);
  894.  
  895.             BltBitMapRastPort(&LocalBitMap,0,0,RPort,Left,Top,Width,Height,0xC0);
  896.         }
  897.     }
  898.     else
  899.         BltBitMapRastPort((struct BitMap *)BitMap,0,0,RPort,Left,Top,Width,Height,0xC0);
  900. }
  901.  
  902. VOID GfxDisplay::DisposeBitMap(struct BitMap *Bits)
  903. {
  904.     if(Bits)
  905.     {
  906.         FreeVec(Bits->Planes[0]);
  907.  
  908.         FreeVec(Bits);
  909.     }
  910. }
  911.  
  912. struct BitMap *GfxDisplay::NewBitMap(LONG Depth,LONG Width,LONG Height)
  913. {
  914.     struct BitMap *Bits;
  915.  
  916.     if(Bits = (struct BitMap *)AllocVec(sizeof(struct BitMap),MEMF_ANY))
  917.     {
  918.         InitBitMap(Bits,8,Width,Height);
  919.  
  920.         if(Depth == 1)
  921.         {
  922.             if(Bits->Planes[0] = (PLANEPTR)AllocVec(Bits->BytesPerRow * Bits->Rows,MEMF_CHIP))
  923.             {
  924.                 LONG i;
  925.  
  926.                 for(i = 1 ; i < 8 ; i++)
  927.                     Bits->Planes[i] = Bits->Planes[0];
  928.             }
  929.         }
  930.         else
  931.         {
  932.             if(Bits->Planes[0] = (PLANEPTR)AllocVec(Depth * Bits->BytesPerRow * Bits->Rows,MEMF_CHIP))
  933.             {
  934.                 LONG PlaneSize = Bits->BytesPerRow * Bits->Rows;
  935.                 LONG i;
  936.  
  937.                 for(i = 1 ; i < Depth ; i++)
  938.                     Bits->Planes[i] = Bits->Planes[i - 1] + PlaneSize;
  939.             }
  940.         }
  941.  
  942.         if(Bits->Planes[0])
  943.             return(Bits);
  944.         else
  945.             FreeVec(Bits);
  946.     }
  947.  
  948.     return(NULL);
  949. }
  950.  
  951. VOID GfxDisplay::SetFgPen(LONG Index)
  952. {
  953.     if(Index != FgPen)
  954.     {
  955.         FgPen = Index;
  956.  
  957.         SetAPen(RPort,Pen[Index]);
  958.     }
  959. }
  960.  
  961. VOID GfxDisplay::SetBgPen(LONG Index)
  962. {
  963.     if(Index != BgPen)
  964.     {
  965.         BgPen = Index;
  966.  
  967.         SetBPen(RPort,Pen[Index]);
  968.     }
  969. }
  970.  
  971. VOID GfxDisplay::SetPens(LONG Fg,LONG Bg)
  972. {
  973.     if(Fg != FgPen || Bg != BgPen)
  974.     {
  975.         FgPen = Fg;
  976.         BgPen = Bg;
  977.  
  978.         SetABPenDrMd(RPort,Pen[Fg],Pen[Bg],JAM2);
  979.     }
  980. }
  981.  
  982. VOID GfxDisplay::Fill(LONG Left,LONG Top,LONG Width,LONG Height)
  983. {
  984.     if(Width > 0 && Height > 0)
  985.     {
  986.         Left    += BtxWindow->BorderLeft;
  987.         Top        += BtxWindow->BorderTop;
  988.  
  989.         RectFill(RPort,Left,Top,Left + Width - 1,Top + Height - 1);
  990.     }
  991. }
  992.  
  993. VOID GfxDisplay::Complement(LONG Left,LONG Top,LONG Width,LONG Height)
  994. {
  995.     if(Width > 0 && Height > 0)
  996.     {
  997.         Left    += BtxWindow->BorderLeft;
  998.         Top        += BtxWindow->BorderTop;
  999.  
  1000.         SetABPenDrMd(RPort,(ULONG)~0,0,JAM1 | COMPLEMENT);
  1001.  
  1002.         RectFill(RPort,Left,Top,Left + Width - 1,Top + Height - 1);
  1003.  
  1004.         SetABPenDrMd(RPort,Pen[FgPen],Pen[BgPen],JAM2);
  1005.     }
  1006. }
  1007.  
  1008. VOID GfxDisplay::SetColour(LONG Index,UBYTE Red,UBYTE Green,UBYTE Blue)
  1009. {
  1010.     SetRGB32(VPort,Pen[Index],SPREAD(Red),SPREAD(Green),SPREAD(Blue));
  1011. }
  1012.  
  1013. ULONG GfxDisplay::WaitMask(VOID)
  1014. {
  1015.     return(WindowMask);
  1016. }
  1017.  
  1018. LONG GfxDisplay::Waiting(VOID)
  1019. {
  1020.     if(WaitingChar == -1)
  1021.     {
  1022.         struct IntuiMessage *Message;
  1023.  
  1024.         while(Message = (struct IntuiMessage *)GetMsg(WindowPort))
  1025.         {
  1026.             if(Message->Class == IDCMP_RAWKEY)
  1027.             {
  1028.                 if((WaitingChar = (WORD)MapKey(Message)) >= 0)
  1029.                 {
  1030.                     ReplyMsg((struct Message *)Message);
  1031.  
  1032.                     return(1);
  1033.                 }
  1034.             }
  1035.             else
  1036.             {
  1037.                 if(Message->Class == IDCMP_CLOSEWINDOW)
  1038.                 {
  1039.                     ReplyMsg((struct Message *)Message);
  1040.  
  1041.                     WaitingChar = '\033';
  1042.  
  1043.                     return(1);
  1044.                 }
  1045.             }
  1046.  
  1047.             ReplyMsg((struct Message *)Message);
  1048.         }
  1049.  
  1050.         return(0);
  1051.     }
  1052.     else
  1053.         return(1);
  1054. }
  1055.  
  1056. LONG GfxDisplay::GetChar(VOID)
  1057. {
  1058.     if(WaitingChar == -1)
  1059.     {
  1060.         struct IntuiMessage *Message;
  1061.  
  1062.         while(Message = (struct IntuiMessage *)GetMsg(WindowPort))
  1063.         {
  1064.             if(Message->Class == IDCMP_RAWKEY)
  1065.             {
  1066.                 LONG Result = MapKey(Message);
  1067.  
  1068.                 ReplyMsg((struct Message *)Message);
  1069.  
  1070.                 return(Result);
  1071.             }
  1072.             else
  1073.             {
  1074.                 if(Message->Class == IDCMP_CLOSEWINDOW)
  1075.                 {
  1076.                     ReplyMsg((struct Message *)Message);
  1077.  
  1078.                     return('\033');
  1079.                 }
  1080.             }
  1081.  
  1082.             ReplyMsg((struct Message *)Message);
  1083.         }
  1084.  
  1085.         return(-1);
  1086.     }
  1087.     else
  1088.     {
  1089.         LONG Result = WaitingChar;
  1090.  
  1091.         WaitingChar = -1;
  1092.  
  1093.         return(Result);
  1094.     }
  1095. }
  1096.  
  1097. LONG GfxDisplay::MapKey(struct IntuiMessage *Message)
  1098. {
  1099.     static LONG Table[][2] =
  1100.     {
  1101.         RAWKEY_CursorUp,    KEY_CursorUp,
  1102.         RAWKEY_CursorDown,    KEY_CursorDown,
  1103.         RAWKEY_CursorRight, KEY_CursorRight,
  1104.         RAWKEY_CursorLeft,    KEY_CursorLeft,
  1105.  
  1106.         RAWKEY_Help,        KEY_Help,
  1107.  
  1108.         RAWKEY_F1,            -1,
  1109.         RAWKEY_F2,            -1,
  1110.         RAWKEY_F3,            -1,
  1111.         RAWKEY_F4,            -1,
  1112.         RAWKEY_F5,            -1,
  1113.         RAWKEY_F6,            -1,
  1114.         RAWKEY_F7,            -1,
  1115.         RAWKEY_F8,            -1,
  1116.         RAWKEY_F9,            -1,
  1117.         RAWKEY_F10,         -1,
  1118.  
  1119.         -1
  1120.     };
  1121.  
  1122.     UBYTE Buffer[10];
  1123.     LONG i;
  1124.  
  1125.     for(i = 0 ; Table[i][0] != -1 ; i++)
  1126.     {
  1127.         if((Message->Code & ~IECODE_UP_PREFIX) == Table[i][0])
  1128.         {
  1129.             if(Message->Code & IECODE_UP_PREFIX)
  1130.                 return(-1);
  1131.             else
  1132.                 return(Table[i][1]);
  1133.         }
  1134.     }
  1135.  
  1136.     Event.ie_Class        = IECLASS_RAWKEY;
  1137.     Event.ie_SubClass     = 0;
  1138.     Event.ie_Code         = Message->Code;
  1139.     Event.ie_Qualifier    = Message->Qualifier;
  1140.     Event.ie_EventAddress = (APTR *) *((ULONG *)Message->IAddress);
  1141.  
  1142.     Buffer[0] = 0;
  1143.  
  1144.     if(MapRawKey(&Event,(char *)&Buffer[0],10,(struct KeyMap *)NULL) > 0)
  1145.         return(Buffer[0]);
  1146.     else
  1147.         return(-1);
  1148. }
  1149.  
  1150. ULONG GfxDisplay::FindBestModeID(Tag FirstTag,...)
  1151. {
  1152.     struct TagItem            *List,
  1153.                             *Item;
  1154.     ULONG                     Mode;
  1155.  
  1156.     ULONG                     BestMode;
  1157.     LONG                     BestWidth,
  1158.                              BestHeight,
  1159.                              BestDepth;
  1160.  
  1161.     ULONG                     MustHave,
  1162.                              MustNotHave;
  1163.     ULONG                     MonitorID;
  1164.     struct ViewPort            *ViewPort;
  1165.     ULONG                     SourceID;
  1166.     UWORD                     NominalWidth,
  1167.                              NominalHeight;
  1168.     UWORD                     DesiredWidth,
  1169.                              DesiredHeight;
  1170.     UBYTE                     Depth;
  1171.  
  1172.     UBYTE                     RedBits;
  1173.     UBYTE                     BlueBits;
  1174.     UBYTE                     GreenBits;
  1175.  
  1176.     struct DisplayInfo         DisplayInfo;
  1177.     struct DimensionInfo     DimensionInfo;
  1178.  
  1179.     LONG                     Width,
  1180.                              Height;
  1181.  
  1182.     MustHave        = NULL;
  1183.     MustNotHave        = SPECIAL_FLAGS;
  1184.     Depth            = 1;
  1185.     MonitorID        = INVALID_ID;
  1186.     SourceID        = INVALID_ID;
  1187.     RedBits            = 4;
  1188.     BlueBits        = 4;
  1189.     GreenBits        = 4;
  1190.     NominalWidth    = 640,
  1191.     NominalHeight    = 200;
  1192.  
  1193.     List = (struct TagItem *)&FirstTag;
  1194.  
  1195.     while(Item = NextTagItem(&List))
  1196.     {
  1197.         switch(Item->ti_Tag)
  1198.         {
  1199.             case BIDTAG_DIPFMustHave:
  1200.  
  1201.                 MustHave = Item->ti_Data;
  1202.                 break;
  1203.  
  1204.             case BIDTAG_DIPFMustNotHave:
  1205.  
  1206.                 MustNotHave = Item->ti_Data;
  1207.                 break;
  1208.  
  1209.             case BIDTAG_RedBits:
  1210.  
  1211.                 RedBits = (UBYTE)Item->ti_Data;
  1212.                 break;
  1213.  
  1214.             case BIDTAG_GreenBits:
  1215.  
  1216.                 GreenBits = (UBYTE)Item->ti_Data;
  1217.                 break;
  1218.  
  1219.             case BIDTAG_BlueBits:
  1220.  
  1221.                 BlueBits = (UBYTE)Item->ti_Data;
  1222.                 break;
  1223.  
  1224.             case BIDTAG_MonitorID:
  1225.  
  1226.                 MonitorID = Item->ti_Data;
  1227.                 break;
  1228.  
  1229.             case BIDTAG_NominalWidth:
  1230.  
  1231.                 NominalWidth = (UWORD)Item->ti_Data;
  1232.                 break;
  1233.  
  1234.             case BIDTAG_NominalHeight:
  1235.  
  1236.                 NominalHeight = (UWORD)Item->ti_Data;
  1237.                 break;
  1238.         }
  1239.     }
  1240.  
  1241.     DesiredWidth    = NominalWidth;
  1242.     DesiredHeight    = NominalHeight;
  1243.  
  1244.     List = (struct TagItem *)&FirstTag;
  1245.  
  1246.     if(ViewPort = (struct ViewPort *)GetTagData(BIDTAG_ViewPort,NULL,List))
  1247.     {
  1248.         NominalWidth    = ViewPort->DWidth;
  1249.         NominalHeight    = ViewPort->DHeight;
  1250.         DesiredWidth    = NominalWidth;
  1251.         DesiredHeight    = NominalHeight;
  1252.         Depth            = ViewPort->RasInfo->BitMap->Depth;
  1253.         SourceID        = GetVPModeID(ViewPort);
  1254.     }
  1255.  
  1256.     if(Item = FindTagItem(BIDTAG_SourceID,List))
  1257.     {
  1258.         if(GetDisplayInfoData((APTR)NULL,(UBYTE *)&DisplayInfo,sizeof(DisplayInfo),DTAG_DISP,SourceID))
  1259.             MustHave = (DisplayInfo.PropertyFlags & SPECIAL_FLAGS) | MustHave;
  1260.         else
  1261.             return(INVALID_ID);
  1262.  
  1263.         if(GetDisplayInfoData((APTR)NULL,(UBYTE *)&DimensionInfo,sizeof(DimensionInfo),DTAG_DIMS,SourceID))
  1264.         {
  1265.             NominalWidth    = (UWORD)(DimensionInfo.Nominal.MaxX - DimensionInfo.Nominal.MinX + 1);
  1266.             NominalHeight    = (UWORD)(DimensionInfo.Nominal.MaxY - DimensionInfo.Nominal.MinY + 1);
  1267.             DesiredWidth    = NominalWidth;
  1268.             DesiredHeight    = NominalHeight;
  1269.         }
  1270.         else
  1271.             return(INVALID_ID);
  1272.     }
  1273.  
  1274.     List = (struct TagItem *)&FirstTag;
  1275.  
  1276.     while(Item = NextTagItem(&List))
  1277.     {
  1278.         switch(Item->ti_Tag)
  1279.         {
  1280.             case BIDTAG_DesiredWidth:
  1281.  
  1282.                 DesiredWidth = (UWORD)Item->ti_Data;
  1283.                 break;
  1284.  
  1285.             case BIDTAG_DesiredHeight:
  1286.  
  1287.                 DesiredHeight = (UWORD)Item->ti_Data;
  1288.                 break;
  1289.  
  1290.             case BIDTAG_Depth:
  1291.  
  1292.                 Depth = (UBYTE)Item->ti_Data;
  1293.                 break;
  1294.         }
  1295.     }
  1296.  
  1297.     BestMode    = INVALID_ID;
  1298.     BestWidth    = 0;
  1299.     BestHeight    = 0;
  1300.     BestDepth    = 0;
  1301.  
  1302.     Mode = INVALID_ID;
  1303.  
  1304.     while((Mode = NextDisplayInfo(Mode)) != INVALID_ID)
  1305.     {
  1306.         if(MonitorID != INVALID_ID)
  1307.         {
  1308.             if((Mode & MONITOR_ID_MASK) != MonitorID)
  1309.                 continue;
  1310.         }
  1311.  
  1312.         if(ModeNotAvailable(Mode) & ~DI_AVAIL_NOTWITHGENLOCK)
  1313.             continue;
  1314.  
  1315.         if(GetDisplayInfoData((APTR)NULL,(UBYTE *)&DisplayInfo,sizeof(DisplayInfo),DTAG_DISP,Mode) && GetDisplayInfoData((APTR)NULL,(UBYTE *)&DimensionInfo,sizeof(DimensionInfo),DTAG_DIMS,Mode))
  1316.         {
  1317.             if(DimensionInfo.MaxDepth < Depth || DisplayInfo.RedBits < RedBits || DisplayInfo.GreenBits < GreenBits || DisplayInfo.BlueBits < BlueBits)
  1318.                 continue;
  1319.  
  1320.             if(DimensionInfo.MaxDepth > 8 && Depth <= 8)
  1321.                 continue;
  1322.  
  1323.  
  1324.             if(MustHave)
  1325.             {
  1326.                 if((DisplayInfo.PropertyFlags & MustHave) != MustHave)
  1327.                     continue;
  1328.             }
  1329.  
  1330.             if(MustNotHave)
  1331.             {
  1332.                 if(DisplayInfo.PropertyFlags & MustNotHave)
  1333.                     continue;
  1334.             }
  1335.  
  1336.             Width    = DimensionInfo.TxtOScan.MaxX - DimensionInfo.TxtOScan.MinX + 1;
  1337.             Height    = DimensionInfo.TxtOScan.MaxY - DimensionInfo.TxtOScan.MinY + 1;
  1338.  
  1339.             if(DesiredWidth <= Width && DesiredHeight <= Height && NominalWidth <= DimensionInfo.Nominal.MaxX - DimensionInfo.Nominal.MinX + 1 && NominalHeight <= DimensionInfo.Nominal.MaxY - DimensionInfo.Nominal.MinY + 1)
  1340.             {
  1341.                 if(!BestWidth || !BestHeight || !BestDepth)
  1342.                 {
  1343.                     BestMode    = Mode;
  1344.                     BestDepth    = DimensionInfo.MaxDepth;
  1345.                     BestWidth    = DesiredWidth;
  1346.                     BestHeight    = DesiredHeight;
  1347.                 }
  1348.                 else
  1349.                 {
  1350.                     if(DimensionInfo.MaxDepth <= BestDepth && Width <= BestWidth && Height <= BestHeight)
  1351.                     {
  1352.                         BestMode    = Mode;
  1353.                         BestDepth    = DimensionInfo.MaxDepth;
  1354.                         BestWidth    = DesiredWidth;
  1355.                         BestHeight    = DesiredHeight;
  1356.                     }
  1357.                 }
  1358.             }
  1359.         }
  1360.     }
  1361.  
  1362.     return(BestMode);
  1363. }
  1364.  
  1365. VOID GfxDisplay::ReleaseColours(VOID)
  1366. {
  1367.     LONG i;
  1368.  
  1369.     for(i = 0 ; i < 60 ; i++)
  1370.     {
  1371.         ReleasePen(VPort->ColorMap,Pen[i]);
  1372.         Pen[i] = -1;
  1373.     }
  1374. }
  1375.  
  1376. BOOL GfxDisplay::InitColours(VOID)
  1377. {
  1378.     int n;
  1379.  
  1380.     init_colormap();
  1381.  
  1382.     for(n = 0 ; n < 16 ; n++)
  1383.     {
  1384.         Pen[n] = (LONG)ObtainBestPen(VPort->ColorMap,SPREAD(colormap[n].red),SPREAD(colormap[n].green),SPREAD(colormap[n].blue),
  1385.             OBP_Precision,    PRECISION_IMAGE,
  1386.             OBP_FailIfBad,    TRUE,
  1387.         TAG_DONE);
  1388.  
  1389.         if(Pen[n] == -1)
  1390.         {
  1391.             ReleaseColours();
  1392.             return(FALSE);
  1393.         }
  1394.     }
  1395.  
  1396.     for(n = 16 ; n < 60 ; n++)
  1397.     {
  1398.         Pen[n] = (LONG)ObtainPen(VPort->ColorMap,(ULONG)-1, 0,0,0, PEN_EXCLUSIVE|PEN_NO_SETCOLOR);
  1399.  
  1400.         if(Pen[n] == -1)
  1401.         {
  1402.             ReleaseColours();
  1403.             return(FALSE);
  1404.         }
  1405.     }
  1406.  
  1407.     for(n = 0 ; n < 8 ; n++)
  1408.     {
  1409.         SetColour(n + 16,colormap[n + 16].red,colormap[n + 16].green,colormap[n + 16].blue);    // clut 2
  1410.         SetColour(n + 24,colormap[n + 24].red,colormap[n + 24].green,colormap[n + 24].blue);    // clut 3
  1411.     }
  1412.  
  1413.     for(n = 0 ; n < 4 ; n++)    // dclut
  1414.         SetColour(32 + n,colormap[32 + n].red,colormap[32 + n].green,colormap[32 + n].blue);
  1415.  
  1416.     for(n = 0 ; n < 24 ; n++)
  1417.         SetColour(32 + 4 + n,colormap[32 + 4 + n].red,colormap[32 + 4 + n].green,colormap[32 + 4 + n].blue);
  1418.  
  1419.     return(TRUE);
  1420. }
  1421.